package com.jweb.framework.core.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.io.Writer;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLResolver;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamResult;

import org.codehaus.stax2.XMLInputFactory2;
import org.codehaus.stax2.XMLOutputFactory2;
import org.codehaus.stax2.io.EscapingWriterFactory;
import org.w3c.dom.Document;

import com.ctc.wstx.stax.WstxInputFactory;
import com.ctc.wstx.stax.WstxOutputFactory;
import com.sun.xml.fastinfoset.stax.StAXDocumentParser;
import com.sun.xml.fastinfoset.stax.StAXDocumentSerializer;
/**
 * 修改人： Thomas
 * 修改内容：新增 
 * 类说明：
 */
public class XMLUtils {
	
	static Boolean a = Boolean.TRUE ;
	
	static Boolean b = Boolean.FALSE ;
	
	private static XMLInputFactory xmlInputFactory = invokeA(true);
	
	/*
	 * XMLOutputFactory 定义用于获取XMLEventWriter 和 XMLStreamWriter 的工厂抽象实现。
	 */
	private static XMLOutputFactory xmlOutputFactory = invokeA();
	
	private static TransformerFactory transformerFactory = TransformerFactory.newInstance() ;
	
	private static AbstractSoftThreadLocal f = new SoftC();
	
	private static AbstractSoftThreadLocal g = new SoftD();
		
	private static XMLInputFactory invokeA(boolean flag) {
		
		
		Thread thread = Thread.currentThread();
		ClassLoader classLoader = thread.getContextClassLoader();
		
		try {
			
			thread.setContextClassLoader(XMLUtils.class.getClassLoader());
			WstxInputFactory wstxInputFactory = new WstxInputFactory();
			wstxInputFactory.setProperty("javax.xml.stream.isValidating", b);
			wstxInputFactory.setProperty("javax.xml.stream.isNamespaceAware", a);
			
			if(wstxInputFactory instanceof XMLInputFactory2){
				XMLInputFactory2 xmlInputFactory2 = wstxInputFactory ;
				xmlInputFactory2.configureForSpeed();
			}
			
			if(flag){
				wstxInputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", Boolean.FALSE);
				/*
				 * XMLResolver 此接口用于在XML解析过程中解析资源。如果应用程序希望执行自定义实体解析，那么它必须使用setXMLResolver方法向XMLInputFactory注册此接口的一个实例。
				 */
				wstxInputFactory.setXMLResolver(new XMLResolver(){

					public Object resolveEntity(String s, String s1, String s2,String s3) throws XMLStreamException {
						
						return new ByteArrayInputStream(new byte[0]);
					}
					
				});
			}
			
			return wstxInputFactory ;
		} finally {
			thread.setContextClassLoader(classLoader);
		}
		
	}
	
	private static XMLOutputFactory invokeA(){
		
		Thread thread = Thread.currentThread();
		ClassLoader classLoader = thread.getContextClassLoader();
		
		try {
			thread.setContextClassLoader(XMLUtils.class.getClassLoader());
			
			WstxOutputFactory wstxOutputFactory = new WstxOutputFactory();
			if(a.booleanValue()){
				wstxOutputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.TRUE);
			}
			if(wstxOutputFactory instanceof XMLOutputFactory2) {
				wstxOutputFactory.setProperty("org.codehaus.stax2.textEscaper", InnerA.a);
				wstxOutputFactory.setProperty("org.codehaus.stax2.attrValueEscaper", InnerA.b);
				wstxOutputFactory.setProperty("javax.xml.stream.isNamespaceAware", a);
				
				XMLOutputFactory2 xmlOutputFactory2 = wstxOutputFactory ;
				xmlOutputFactory2.configureForSpeed();
			}
			
			return wstxOutputFactory ;
		} finally {
			thread.setContextClassLoader(classLoader);
		}
	}
	
	public static XMLStreamWriter createXMLWriter(OutputStream outputStream , String encoding , boolean flag) throws XMLStreamException {
		
		if(flag) {
			StAXDocumentSerializer stAXDocumentSerializer = (StAXDocumentSerializer) f.get();
			stAXDocumentSerializer.setOutputStream(outputStream);
			stAXDocumentSerializer.setEncoding(encoding);
			return stAXDocumentSerializer ;
		}
		if(encoding!=null && encoding.length()>0){
			return xmlOutputFactory.createXMLStreamWriter(outputStream , encoding);
		}
		// createXMLStreamWriter(OutputStream stream)：创建一个写入到流的新XMLStreamWriter.
		return xmlOutputFactory.createXMLStreamWriter(outputStream); // xmlOutputFactory=com.ctc.wstx.stax.WstxOutputFactory
	}
	
	
	public static XMLStreamWriter createXMLWriter(Writer writer) throws XMLStreamException {
		return xmlOutputFactory.createXMLStreamWriter(writer);
	}
	
	public static XMLStreamWriter createXMLWriterQuietly(OutputStream outputStream , String encoding , boolean flag) {
		try {
			return createXMLWriter(outputStream , encoding , flag);
		} catch (Exception e) {
			throw new IllegalStateException(e);
		}
	}
	
	
	public static XMLStreamReader createXMLReader(InputStream inputStream , String encoding , boolean flag) throws XMLStreamException {
		if(flag){// false
			StAXDocumentParser stAXDocumentParser = (StAXDocumentParser) g.get();
			stAXDocumentParser.setInputStream(inputStream);
			return stAXDocumentParser ;
		}
		if(encoding!=null && encoding.length()>0){//true
			return xmlInputFactory.createXMLStreamReader(inputStream , encoding); //此处会读取传输流中的相关信息。
		}//createXMLStreamReader(InputStream stream,String encoding)根据java.io.InputStream创建一个新XMLStreamReader.
		return xmlInputFactory.createXMLStreamReader(inputStream);
	}
	
	public static XMLStreamReader createXMLReaderQuietly(InputStream inputStream , String encoding , boolean flag){
		try {
			return createXMLReader(inputStream , encoding , flag);
		} catch (Exception e) {
			throw new IllegalStateException(e);
		}
	}
	
	public static byte[] toBytes(Source source) throws TransformerException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		StreamResult streamResult = new StreamResult(baos);
		transform(source , streamResult);  // "source"=org.springframework.xml.transform.StaxSource
		return baos.toByteArray();
	}
	
	public static InputStream toInputStream(Source source) throws TransformerException {
		return new ByteArrayInputStream(toBytes(source));
	}
	
	public static Document toDocument(Source source) throws TransformerException {
		DOMResult domResult = new DOMResult();
		transform(source , domResult);
		Document document = (Document) domResult.getNode();
		return document ;
	}
	
	public static void transform(Source source , Result result) throws TransformerException {
		Transformer transformer = transformerFactory.newTransformer();
		transformer.transform(source, result); // transformer=com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl
	}
	
	static class InnerA
	  {
	    public static EscapingWriterFactory a = new b();

	    public static EscapingWriterFactory b = new a();

	    static class a implements EscapingWriterFactory
	    {
	      public Writer createEscapingWriterFor(Writer paramWriter, String paramString) throws UnsupportedEncodingException {
	        return new FilterWriterA(paramWriter, paramString, '"', false);
	      }

	      public Writer createEscapingWriterFor(OutputStream paramOutputStream, String paramString) throws UnsupportedEncodingException {
	        throw new IllegalArgumentException("not supported");
	      }
	    }

	    static class b
	      implements EscapingWriterFactory
	    {
	      public Writer createEscapingWriterFor(Writer paramWriter, String paramString)
	        throws UnsupportedEncodingException
	      {
	        return new FilterWriterE(paramWriter, paramString, false);
	      }

	      public Writer createEscapingWriterFor(OutputStream paramOutputStream, String paramString) throws UnsupportedEncodingException {
	        throw new IllegalArgumentException("not supported");
	      }
	    }
	  }
	
	

}
